/*
* INSANE - Interactive Structural Analysis Environment
*
* Copyright (C) 2003-2005
* Universidade Federal de Minas Gerais
* Escola de Engenharia
* Departamento de Engenharia de Estruturas
* 
* Author's email :    insane@dees.ufmg.br
* Author's website :  http://www.dees.ufmg.br/insane
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
package br.ufmg.dees.insane.model.femModel.node;
import java.util.HashMap;

import br.ufmg.dees.insane.util.IPoint3d;
import br.ufmg.dees.insane.util.pointValues.DoublePointValues;
import br.ufmg.dees.insane.util.pointValues.IntPointValues;
import br.ufmg.dees.insane.util.pointValues.PointValues;


/**
 * A class representing a node.
 * @author  Fonseca, Flavio & Pitangueira, Roque, CENOURA!!!
 * @version  1.0
 * @since  September 2003
 */

public class Node extends IPoint3d implements java.io.Serializable {
	
	
	private static final long serialVersionUID = 1L;

	/** The label of this Node. */
	protected String label;
	
	/** The point of this Node. */
	protected IPoint3d point;
	
	/** The values of this Node. */
	protected HashMap<String, Object> nodeValues;
	
	/** The possible keys for the Map. */
	/** The six possible stateVariables of this Node.<br>
	*They are stored in this order: <i>x, y, z, x, y, z</i>*/
	public static String STATE_VARIABLE = "STATE_VARIABLE";
	
	/** The key for six possible dualVariables on this Node.<br>
	*They are stored in this order: <i>Fx, Fy, Fz, Mx, My, Mz</i><p>
	* <i><b>It must be informed in this node's local axis.</b></i>*/
	public static String DUAL_VARIABLE = "DUAL_VARIABLE";
    
	/** The key for six possible restraints of this Node.<p>
	*<i>true</i> = There is a restriction.<br>
	*<i>false</i> = There is no restriction.<p>
	*The restrictions in each position are related to these stateVariables: <i>Dx, Dy, Dz, Rx, Ry, Rz</i>*/
	public final String RESTRAINTS = "RESTRAINTS";
	
	/** The key for number of the equations of this Node.<br>
	* They are related to these stateVariables: <i>Dx, Dy, Dz, Rx, Ry, Rz</i>*/
	public final String EQUATIONS = "EQUATIONS";
	
	/** The prescribed stateVariables of this Node.
	* They are stored in this order: <i>Dx, Dy, Dz, Rx, Ry, Rz</i>*/
	public static String PRE_STATE_VARIABLE = "PRE_STATE_VARIABLE";
	
	/** The key for prescribed dualVariables of this Node. */
	public static String PRE_DUAL_VARIABLE = "PRE_DUAL_VARIABLE";
	
	/** The key for six possible unknow dualVariables on this Node.<br>
	*They are stored in this order: <i>Fx, Fy, Fz, Mx, My, Mz</i><p>
	* <i><b>It is informed in this node's local axis.</b></i>*/
	public static String UNKNOWN_DUAL_VARIABLE = "UNKNOWN_DUAL_VARIABLE";

	/** The possible keys for the Map. */
	/** The possible dofLabels of this Node.<br>
	*/
	public final String DOF_LABELS = "DOF_LABELS";

	/** The coeficients A,B,C */
	public final String COEFICIENTS_A = "COEFICIENTS_A";
	public final String COEFICIENTS_B = "COEFICIENTS_B";
	public final String COEFICIENTS_C = "COEFICIENTS_C";
	
	
	/** The angle between the local X axis and the global X axis.<p>
	* It is positive in the counter-clockwise way.*/
	protected double angle;
		
	/**Constructs a Node and sets its Point and initalize the map.
     * @param p The point of this Node.
     */
	  public Node(IPoint3d p) {
	      this.point=p;
	      this.nodeValues = new HashMap<String, Object>(10);
	  }
	  
	  /**Constructs a Node and and initalize the map.*/
	  public Node() {
	      this.nodeValues = new HashMap<String, Object>(10);
	  }
	  
	/**
	 * Returns the label of this Node.
	 * @return  The label of this Node.
	 * @uml.property  name="label"
	 */
	public String getLabel(){
		return (label);
	};
	
	/**
	 * Sets the label of this Node.
	 * @param a  The label of this Node.
	 * @uml.property  name="label"
	 */
	public void setLabel(String a){
		label = a;
	};
	
	/**
	 * Returns the point of this Node.
	 * @return  The point of this Node..
	 * @uml.property  name="point"
	 */
	public IPoint3d getPoint() {
		return (point);
	};
	
	/**
	 * Sets the point of this Node.
	 * @param a  The point of this Node.
	 * @uml.property  name="point"
	 */
	public void setPoint(IPoint3d a) {
		point = a;
	};
	
	/**
	 * Returns this Node's angle.
	 * @return  This Node's angle.
	 * @uml.property  name="angle"
	 */
	public double getAngle()
	{
		return (angle);
	};
	
	/**
	 * Sets this Node's angle.
	 * @param a  This Node's angle.
	 * @uml.property  name="angle"
	 */
	public void setAngle(double a)
	{
		angle = a;
	}
	
	/** Sets to zero all the results calculated. */
	public void cleanResults() {
	}
	
  /** Returns the node point values.
   * @param key The key of the point values.
   * @return The node point values.
   */
  public PointValues getNodeValues(String key) {
      return (PointValues)nodeValues.get(key);
  }
  
//  /** Returns the node dual variables values for the load case lc.
//   * @param lc The load case.
//   * @return The node dual variables point values.
//   */
//  public PointValues getNodeDualVariablesValues(String lc) {
//      return ((PointValues)((HashMap)nodeValues.get(this.DUAL_VARIABLE)).get(lc));
//  }
  
//  /** Returns true if the node has dual variables values for the load case lc.
//   * @param lc The loadCase of the point values.
//   * @return True if the node has dual variables values for the load case lc.
//   */
//  public boolean nodeDualVariablesValuesContainsLoadCase(String lc) {
//      return ((HashMap)nodeValues.get(this.DUAL_VARIABLE)).containsKey(lc);
//  }
  
  /** Returns true if the node has the point values for the key.
   * @param key The key of the point values.
   * @return True if the node has the point values for the key.
   */
  public boolean nodeValuesContainsKey(String key) {
      return nodeValues.containsKey(key);
  }
  
  /** Sets a point value at a key of Node Values.
   * @param key The key to set the point values.
   * @param pv The node point values to set.
   */
  public void setNodeValues(String key, PointValues pv) {
      this.nodeValues.put(key, pv);
  }
  
  /** Sets a hashMap at a key of Node Values.
   * @param key The key to set the point values.
   * @param hm The node hashMap to set.
   */
  
  public void setNodeValues(String key, HashMap hm) {
      nodeValues.put(key, hm);
  }
  
  /** Adds a point value at a key of Node Values.
   * @param key The key to set the point values.
   * @param pv The node point values to set.
   */
  public void addNodeValues(String key, DoublePointValues dpv) {
	  DoublePointValues pv = (DoublePointValues)this.getNodeValues(key);
	  pv.add(dpv);
      this.setNodeValues(key, pv);
  }
  
  /** Adds a point value at a key of Node Values.
   * @param key The key to set the point values.
   * @param pv The node point values to set.
   */
  public void initNodeValues(String key, DoublePointValues dpv) {
	  DoublePointValues pv = (DoublePointValues)this.getNodeValues(key);
	  pv.set(dpv);
      this.setNodeValues(key, pv);
  }
  
//  /** Sets a key to the loadsCaseMap of Node Values.
//   * @param key The key to set the load case.
//   */
//  public void setNodeLoadCase(String key, DoublePointValues dpv) {
//      ((HashMap)nodeValues.get(this.DUAL_VARIABLE)).put(key,dpv);
//  }
  
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.util.IPoint3d#getCoords()
     */
    public double[] getCoords() {
        return this.getPoint().getCoords();
    }
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.util.IPoint3d#getX()
     */
    public double getX() {
        return this.getPoint().getX();
    }
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.util.IPoint3d#getY()
     */
    public double getY() {
        return this.getPoint().getY();
    }
    /* (non-Javadoc)
     * @see br.ufmg.dees.insane.util.IPoint3d#getZ()
     */
    public double getZ() {
        return this.getPoint().getZ();
    }

	/**
	 * The method return the nodeValues.
	 * @return  Returns The nodeValues.
	 */
	public HashMap getNodeValues() {
		return this.nodeValues;
	}

	/**
	 * The method set the field nodeValues from the parameter nodeValues.
	 * @param nodeValues  The nodeValues to set.
	 */
	public void setNodeValues(HashMap<String, Object> nodeValues) {
		this.nodeValues = nodeValues;
	}
	
	/** Return the number of degress of freedom of this Node.
	*@return The number of degrees of freedom.
	*/
	public int getNumberOfDegreesOfFreedom() {
		PointValues pv = this.getNodeValues(this.DOF_LABELS);
		return pv.getSize();
  }
	
	/** The method initilizes the unknown variables of the node.
	 * 	@param dofLabels The labels of the degrees of freedom of this Node.
	*/
	public void init(PointValues dofLabels) {
		this.setNodeValues(this.DOF_LABELS, dofLabels);
		DoublePointValues stateVar = new DoublePointValues();
		DoublePointValues dualVar = new DoublePointValues();
		DoublePointValues unknowDualVar = new DoublePointValues();
		IntPointValues  equations = new IntPointValues();
		for(int i=0; i<dofLabels.getSize(); i++){
			stateVar.addPointValue(0.0);
			dualVar.addPointValue(0.0);
			unknowDualVar.addPointValue(0.0);
			equations.addPointValue(0);
	    }
		this.setNodeValues(Node.STATE_VARIABLE, stateVar);
		this.setNodeValues(Node.UNKNOWN_DUAL_VARIABLE, unknowDualVar);
		this.setNodeValues(this.EQUATIONS, equations);
		this.setNodeValues(Node.DUAL_VARIABLE, dualVar);
  }
	
}
